<?php
namespace app\common\model\cms;

use app\common\model\BaseModel;
use org\util\DbHelper;
use org\util\FileUtil;
use think\facade\Cache;
use think\facade\Env;
use think\helper\Str;

class MoudleModel extends BaseModel
{
    protected $name = 'cms_moudle';
    protected $pk='id';

    protected $autoWriteTimestamp = true;
    /**
     * 需要添加静态class的控件
     * @var array
     */
    protected $staticClass = ['textarea','ckeditor','checkbox','radio','input_array','images','images_desc','files'];
    /**
     * 初始化表单
     * @param $id
     */
    public function initForm($id,$type='add'){
        $info = Cache::get('cms_moudle_'.$id);
        $metaList = $info['meta'];
        $mainForm=[];
        $subForm=[];
        //补充专题选择
        if($type=='add'){
            $subForm[] = <<<EOT
                            <div class="form-group ">
                                <label class="col-sm-2 control-label">专题</label>
                                <div class="col-sm-10">
{:FormBuild::_selectpages('special_ids','',[
    'data-url'=>'/admin/special/selectpage.html',
    'data-show'=>'special_name',
    'data-key'=>'id'
])}
                                </div>
                            </div>
EOT;
        }else{
            $subForm[] = <<<EOT
                            <div class="form-group ">
                                <label class="col-sm-2 control-label">专题</label>
                                <div class="col-sm-10">
{:FormBuild::_selectpages('special_ids',\$info['special_ids'],[
    'data-url'=>'/admin/special/selectpage.html',
    'data-show'=>'special_name',
    'data-key'=>'id'
])}
                                </div>
                            </div>
EOT;
        }
        foreach($metaList as $k=>$v){
            $options = json_decode(html_out($v['form_config']),true);
            //静态class
            $staticClass = in_array($v['form_type'],$this->staticClass) ? 'form-control-static' : '';
            //必填class
            $requireClass = empty($v['valid'])?'':'require';
            //前端验证规则处理
            $datatype = \FormBuild::transformationValid($v['valid']);
            if(!empty($datatype)) $options['datatype']=$datatype;
            //转换表单
            if(!empty($options)){
                $options = ','.arr2export($options);
            }else{
                $options = '';
            }
            $fun = '_'.$v['form_type'];
            if($type=='add'){
                if($v['field_name']=='class_id'){ //处理class_id
                    $form="{:FormBuild::{$fun}('{$v['field_name']}',\$Request.param.class_id,[
    'list-data'=>\$classList,
    'items-name'=>'_name',
    'empty-option'=>'|请选择栏目',
    'datatype'=>'*'
])}";
                }else{
                    $form="{:FormBuild::{$fun}('{$v['field_name']}','{$v['default_value']}'$options)}";
                }
            }else{
                if($v['field_name']=='class_id'){ //处理class_id
                    $form="{:FormBuild::{$fun}('{$v['field_name']}',\$info['{$v['field_name']}'],[
    'list-data'=>\$classList,
    'items-name'=>'_name',
    'empty-option'=>'|请选择栏目',
    'datatype'=>'*'
])}";
                }else{
                    $form="{:FormBuild::{$fun}('{$v['field_name']}',\$info['{$v['field_name']}']$options)}";
                }
            }
            $formHtml=<<<EOT
                            <div class="form-group ">
                                <label class="col-sm-2 control-label {$requireClass}">{$v['display_name']}</label>
                                <div class="col-sm-10 {$staticClass}">
{$form}
                                </div>
                            </div>
EOT;
            if($v['form_type']=='hidden'){ //隐藏框不需要展示内容
                $formHtml=$form;
            }
            if($v['is_main']==1){
                $mainForm[]=$formHtml;
            }else{
                $subForm[]=$formHtml;
            }
        }
        $mainFormHtml=implode(PHP_EOL,$mainForm);
        $subFormHtml=implode(PHP_EOL,$subForm);
        $code=<<<EOT
{extend name="admin@public/layout" /}
{block name="head"}{/block}
{block name="body"}
<body class="bg-gray-light">
<div class="wrapper">
    <section class="content">
        <form class="form-horizontal" id="form" data-callfn="refreshTable">
            <div class="row">
                <div class="col-sm-8">
                    <div class="box">
                        <div class="box-body">
{$mainFormHtml}
                        </div>
                    </div>
                </div>
                <div class="col-sm-4">
                    <div class="box">
                        <div class="box-body">
{$subFormHtml}
                        </div>
                    </div>
                </div>
            </div>
            <div class="fixed-foot text-right">
                <span class="valid-msg text-danger" style="margin-left:10px;display:none;"></span>
                {:FormBuild::_button('立即保存',['class'=>'btn btn-info btn-sub'])}
            </div>
        </form>
    </section>
</div>
<div style="height:15px;"></div>
</body>
<script>
    $(function () {
        formHelper.initForm();
        utils.ajaxSubForm();
    });
</script>
{/block}
EOT;
        return $code;
    }
    /**
     * 初始化模型代码
     * @param $id
     * @return bool
     * @throws \Exception
     */
    public function initModel($id){
        try{
            $info = Cache::get('cms_moudle_'.$id);
            $metaList = $info['meta'];
            $studlyName = Str::studly(str_replace('cms_','',$info['table_name'])); //TableArticle
            $getAttr=[];
            $setAttr=[];
            $typeArr=[];
            $editExtend=[];
            foreach($metaList as $v){
                $attrName = Str::studly($v['field_name']);
                //处理空数据不经过修改器控件
                if(in_array($v['form_type'],['checkbox','images','images_desc','files'])){
                    $editCode = <<<EOT
            if(!request()->has('{$v['field_name']}')){
                \$data['{$v['field_name']}']='';
            }
EOT;
                    $editExtend[]=$editCode;
                }
                //复选框,多图上传处理 逗号分隔
                if (in_array($v['form_type'],['checkbox','images'])) {
                    if($v['form_type']==''){
                        $attrCode=<<<CODE
    protected function get{$attrName}Attr(\$value)
    {
        if(empty(\$value)){
            return '';
        }else{
            return explode(",",\$value);
        }

    }
CODE;
                        $getAttr[]=$attrCode;
                    }
                    $attrCode=<<<CODE
    protected function set{$attrName}Attr(\$value)
    {
        if(empty(\$value)){
            return '';
        }else{
            return implode(",",\$value);
        }
    }
CODE;
                    $setAttr[]=$attrCode;
                }
                //日期类型转换
                if ($v['form_type'] == 'laydate') {
                    $type = isset($v['form_config']['type']) ? $v['form_config']['type'] : 'date';
                    if($type=='date') $typeArr[] = "'{$v['field_name']}'=>'timestamp:Y-m-d'";
                    if($type=='datetime') $typeArr[] = "'{$v['field_name']}'=>'timestamp:Y-m-d H:i:s'";
                    if($type=='year') $typeArr[] = "'{$v['field_name']}'=>'timestamp:Y'";
                    if($type=='month') $typeArr[] = "'{$v['field_name']}'=>'timestamp:Y-m'";
                    if($type=='time') $typeArr[] = "'{$v['field_name']}'=>'timestamp:H:i:s'";
                }
                //富文本读取器
                if($v['form_type']=='ckeditor'){
                    $attrCode=<<<CODE
    protected function get{$attrName}Attr(\$value)
    {
        return \$this->formatContent(\$value);
    }
CODE;
                    $getAttr[] = $attrCode;
                }
                //多图上传带描述
                if($v['form_type']=='images_desc'){
                    //读取器
                    $attrCode=<<<CODE
    protected function get{$attrName}Attr(\$value)
    {
        return json_decode(\$value,JSON_UNESCAPED_UNICODE);
    }
CODE;
                    $getAttr[] = $attrCode;
                    //修改器
                    $attrCode=<<<CODE
    protected function set{$attrName}Attr(\$value)
    {
        return \$this->formatMultiImageDesc(\$value);
    }
CODE;
                    $setAttr[] = $attrCode;
                }

            }
            $typeCode    = implode(',' . PHP_EOL, $typeArr);
            $getCode    = implode(PHP_EOL, $getAttr);
            $setCode    = implode(PHP_EOL, $setAttr);
            $editExtend = implode(PHP_EOL,$editExtend);
            $modelCode=<<<EOT
<?php
namespace app\\common\\model\\cms;

use app\\common\\model\\BaseModel;

class {$studlyName}Model extends BaseModel
{
    protected \$name = '{$info['table_name']}';
    protected \$pk='id';
    //开启自动写入时间戳
    protected \$autoWriteTimestamp = true;
    //设置类型转换
    protected \$type = [
{$typeCode}
    ];
    //读取器
{$getCode}
    //修改器
{$setCode}

    /**
     * 获取内容
     */
    public function getInfo(\$map) {
        \$info = \$this->where(\$map)->find();
        \$info['special_ids'] = D('SpecialItem')->getSpecialIdsByContentId(\$info['moudle_id'],\$info['id']);
        return \$info;
    }
    /**
     * 添加内容
     * @param \$data
     * @return TableArticleModel|void
     * @throws \\Exception
     */
    public function addData(\$data){
        try{
{$editExtend}  
            \$info = self::create(\$data);
        }catch (\Exception \$e){
            exception(\$e->getMessage(),40001);
        }
        return \$info;
    }
    /**
     * 编辑内容
     * @param \$data
     * @return TableArticleModel|void
     * @throws \\Exception
     */
    public function editData(\$data){
        try{
{$editExtend}
            \$info = self::update(\$data);
        }catch (\Exception \$e){
            exception(\$e->getMessage(),40001);
        }
        return \$info;
    }
    /**
     * 删除内容
     * @param \$data
     * @return TableArticleModel|void
     * @throws \\Exception
     */
    public function delData(\$id){
        try{
            \$this->where('id','in',\$id)->delete();
        } catch (\Exception \$e){
            exception(\$e->getMessage(),40001);
        }
        return true;
    }
}
EOT;
        }catch (\Exception $e){
            exception($e->getMessage(),$e->getCode());
        }
        //备份模型文件
        $modelFile = Env::get('app_path') . '/common/model/cms/' . $studlyName . 'Model.php';
        $bakModelFile = Env::get('app_path') . '/common/model/cms/bak/'. date('YmdHis') . $studlyName . 'Model.php';
        if(file_exists($modelFile)) FileUtil::copyFile($modelFile,$bakModelFile);
        return $modelCode;
    }

    /**
     * 初始化列表代码
     * @return string
     */
    public function initList(){
        $html = <<<EOT
{extend name="admin@public/layout" /}
{block name="head"}{/block}
{block name="body"}
<body class="bg-gray-light">
<div class="wrapper">
    <section class="content">
        <div class="nav-tabs-custom">
            <ul class="nav nav-tabs">
                {volist name="modelList" id="vo"}
                <li {eq name="Request.param.moudle_id" value="\$vo['id']"}class="active"{/eq}><a href="/admin/cms.content/index.html?moudle_id={\$vo.id}">{\$vo.name}</a></li>
                {/volist}
            </ul>
            <div class="box-header">
                <form class="form-inline" id="searchForm">
                    <input type="hidden" id="moudle_id" name="moudle_id" data-own="1" value="{\$Request.param.moudle_id}" data-op="=" />
                    <div class="form-group">
                        <label>栏目</label>
                        <select class="form-control" name="class_id" id="class_id" data-own="1" onchange="$('#grid').bootstrapTable('refresh');" style="width:220px;">
                            <option value="">全部栏目</option>
                            {volist name="classList" id="vo"}
                            <option value="{\$vo.id}">{\$vo._name|raw}</option>
                            {/volist}
                        </select>
                    </div>
                    <div class="form-group">
                        <label>状态</label>
                        <select class="form-control" name="is_audit" data-op="=" onchange="$('#grid').bootstrapTable('refresh');">
                            <option value="">全部</option>
                            <option value="1">已审</option>
                            <option value="0">未审</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label>标题</label>
                        <input type="text" class="form-control" id="title" name="title" value="" data-op="like" placeholder="请输入标题"/>
                    </div>
                    <div class="form-group">
                        <button type="button" class="btn btn-default" onclick="$('#grid').bootstrapTable('refresh');">
                            <i class="fa fa-search"></i> 检索
                        </button>
                    </div>
                </form>
            </div>
            <div class="box-body">
                <div class="toolbar">
                    <div class="pull-left">
                        <button type="button" class="btn btn-primary" onclick="doAction.add('{\$Request.param.moudle_id}');">
                            <i class="fa fa-plus"></i> 添加
                        </button>
                        <button type="button" class="btn btn-danger" onclick="doAction.del('{\$Request.param.moudle_id}');">
                            <i class="fa fa-trash"></i> 删除
                        </button>
                    </div>
                </div>
                <table id="grid"
                       data-id-field="id"
                       data-editable-emptytext="empty"
                       data-editable-url="/admin/cms.content/editable.html?moudle_id={\$Request.param.moudle_id}"></table>
            </div>
        </div>
    </section>
</div>
</body>
<script>
    utils.btable({
        url: '/admin/cms.content/index.html',
        singleSelect: false, //是否启用单选
        sortName:'show_order',
        sortOrder:'asc',
        columns: [
            {field: 'state', checkbox: true},
            {field: 'title', title: '标题'},
            {field: 'is_audit', title: '审核', width:80,
                formatter: function (value, row, index) {
                    var html = '';
                    if (value == 1) {
                        html = '<label class="label label-success" onclick="utils.doAction(this,\'refreshTable\')" ' +
                            'data-url="/admin/cms.content/multi.html?moudle_id={\$Request.param.moudle_id}" ' +
                            'data-params="ids=' + row.id + '&params=is_audit:0">已审</label>';
                    } else {
                        html = '<label class="label label-warning" onclick="utils.doAction(this,\'refreshTable\')" ' +
                            'data-url="/admin/cms.content/multi.html?moudle_id={\$Request.param.moudle_id}" ' +
                            'data-params="ids=' + row.id + '&params=is_audit:1">未审</label>';
                    }
                    return html;
                }
            },
            {field: 'show_order', title: '排序', width:80,
                editable: {
                    type:'text',
                    validate: function (value) { //验证规则自定义
                        if (!valid.isNum(value)) return {newValue:'0',msg:'排序填写不正确'};
                    }
                }
            },
            {field: 'operate', title: '操作', width:120,
                formatter: function (value, row, index) {
                    var html = '';
                    html += '<a href="javascript:;" class="btn btn-primary btn-xs" onclick="doAction.edit('+row.moudle_id+',' + row.id + ')">编辑</a> ';
                    html += '<a href="javascript:;" class="btn btn-danger btn-xs" onclick="doAction.del('+row.moudle_id+',' + row.id + ')">删除</a>';
                    return html;
                }
            }
        ]
    });
    var doAction = {
        add: function () {
            var moudle_id = parseInt($('#moudle_id').val());
            var class_id = $('#class_id').val();
            var class_id = valid.isEmpty(class_id) ? '' : class_id;
            var index=utils.openDialog({
                title: '添加内容',
                area: ['800px', '420px'],
                content: '/admin/cms.content/add.html?moudle_id='+moudle_id+'&class_id='+class_id
            });
            layer.full(index);
        },
        edit: function (moudle_id,id) { //修改模型
            var index=utils.openDialog({
                title: '修改模型',
                area: ['800px', '420px'],
                content: '/admin/cms.content/edit.html?moudle_id='+moudle_id+'&id=' + id
            });
            layer.full(index);
        },
        del:function (moudle_id,ids) {
            if(typeof ids=='undefined'){
                var ids = $.map($('#grid').bootstrapTable('getSelections'),function (row,index) {
                    return row.id;
                });
                if(ids.length==0){
                    layer.msg('请选择删除数据');
                    return false;
                }
            }
            layer.confirm('确认删除吗？',{icon:3},function (index) {
                layer.close(index);
                $.post('/admin/cms.content/del.html',{id:ids.join(','),moudle_id:moudle_id},function (res) {
                    if(res.code==1){
                        layer.msg('删除成功！',{icon:1,time:1200},function () {
                            $('#grid').bootstrapTable('refresh');
                        });
                    }else{
                        layer.msg(res.msg);
                    }
                });
            });
        }
    };
</script>
{/block}
EOT;
        return $html;
    }

    /**
     * 添加模型
     * @param $data
     */
    public function addData($data){
        $moudleMetaModel = new MoudleMetaModel();
        self::startTrans();
        try{
            $tableName = "cms_table_".$data['table_name'];
            if(DbHelper::checkTable($tableName)===true) exception('模型表名已存在');
            //添加数据
            $data['table_name'] = $tableName;
            $info = self::create($data);
            //获取初始化sql建对应内容表
            $sql = file_get_contents(Env::get('APP_PATH') . 'admin/sql/cms.sql');
            $sql = preg_replace(['/@table@/', '/@table_comment@/'], [$tableName, $data['remark']], $sql);
            $this->execute($sql);
            //初始化字段配置内容
            $moudleMetaModel->fieldInit($tableName,$info['id']);
            $this->updateCache();
            self::commit();
        }catch (\Exception $e){
            self::rollback();
            exception($e->getMessage(),$e->getCode());
        }
        return $info;
    }

    /**
     * 编辑模型
     * @param $data
     * @return BaseModel|void
     */
    public function editData($data){
        try{
            $info = self::update($data);
            $this->updateCache();
        }catch (\Exception $e){
            exception($e->getMessage(),$e->getCode());
        }
        return $info;
    }

    /**
     * 删除模型
     * @param $id
     */
    public function delData($id){
        self::startTrans();
        try{
            $info = $this->where('id',$id)->find();
            //系统内置不允许删除
            if(in_array($info['id'],[1,2,3])) exception('系统内置模型不可以删除！');
            //存在模型栏目不允许删除
            if(ClassModel::where('moudle_id',$id)->find()) exception('存在对应模型栏目，不允许删除！');
            //删除表模型
            $this->where('id',$id)->delete();
            //删除表字段配置
            MoudleMetaModel::where('moudle_id',$id)->delete();
            //删除对应表名
            $this->execute("DROP TABLE IF EXISTS `{$info['table_name']}`");
            $this->updateCache();
            self::commit();
        }catch (\Exception $e){
            self::rollback();
            exception($e->getMessage(),$e->getCode());
        }
        //尝试删除对应模型和验证器文件
        try{
            $file = Str::studly(str_replace('cms_','',$info['table_name']));
            FileUtil::unlinkFile(Env::get('APP_PATH') . '/common/model/cms/' . $file . 'Model.php');
        }catch (\Exception $e){}
        return true;
    }
    /**
     * 更新缓存
     */
    public function updateCache(){
        $moudleMetaModel = new MoudleMetaModel();
        $moudle = $this->order('show_order asc')->column('id,name,table_name,remark,status,show_order','id');
        foreach($moudle as $k=>$v){
            $meta = $moudleMetaModel->where('moudle_id',$v['id'])->order('show_order asc')->select()->toArray();
            $v['meta'] = $meta;
            Cache::set('cms_moudle_'.$v['id'],$v);
        }
    }

}